package com.dongdong.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.dongdong.api.SellerAPI;
import com.dongdong.em.Result;
import com.dongdong.em.ResultEnum;
import com.dongdong.mapper.TbSeckillGoodsMapper;
import com.dongdong.model.TbSeckillGoods;
import com.dongdong.model.TbSeckillGoodsExample;
import com.dongdong.model.TbSeckillOrder;
import com.dongdong.model.TbSeller;
import com.dongdong.service.SeckillGoodsService;
import com.dongdong.service.SeckillOrderService;
import com.dongdong.util.IdWorker;
import com.dongdong.vo.SeckillGoodsVO;
import com.dongdong.vo.SeckillOrderVO;
import com.dongdong.vo.SellerVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.xml.crypto.Data;
import java.util.Date;
import java.util.List;

@Service
public class SeckillGoodsServiceImpl implements SeckillGoodsService {

    @Autowired
    private TbSeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SellerAPI sellerAPI;

    @Autowired
    private SeckillOrderService orderService;

    @Override
    public void redisHot() {
        TbSeckillGoodsExample example = new TbSeckillGoodsExample();
        //秒杀开始时间  <=  当前时间  <=  结束时间
        Date date = new Date();
        example.createCriteria().andStartTimeLessThanOrEqualTo(date)//开始时间小于当前时间
                .andEndTimeGreaterThanOrEqualTo(date);//结束时间大于当前时间
        //查询
        List<TbSeckillGoods> tbSeckillGoods = seckillGoodsMapper.selectByExample(example);
        //直接使用stream流进行循环遍历
        tbSeckillGoods.stream().map(seckillList -> {
            SeckillGoodsVO vo = new SeckillGoodsVO();
            BeanUtils.copyProperties(seckillList, vo);
            return vo;
        }).forEach(x -> {
            //存到redis中
            redisTemplate.boundHashOps("SeckillGoodsVO").put(x.getId(), x);//这里的 X 表示整个 VO
        });
    }


    @Override
    public List<SeckillGoodsVO> getSeckillGoods() {
        //从redis中获取秒杀的商品信息   values:获取所有的值    不需要获取小key
        List<SeckillGoodsVO> seckillGoodsVO = redisTemplate.boundHashOps("SeckillGoodsVO").values();
        return seckillGoodsVO;
    }

    @Override
    @SentinelResource("goods")
    public void select() {
        System.out.println("查询订单");
    }


    @Override
    public SeckillGoodsVO selectById(Long id) {
        //根据id查询  秒杀商品信息
        TbSeckillGoods tbSeckillGoods = seckillGoodsMapper.selectByPrimaryKey(id);
        SeckillGoodsVO seckillGoodsVO = new SeckillGoodsVO();
        BeanUtils.copyProperties(tbSeckillGoods, seckillGoodsVO);

        //根据sellerid  查询商家信息
        TbSeller tbSellerResult = sellerAPI.getSellerByName(tbSeckillGoods.getSellerId());

        SellerVO sellerVO = new SellerVO();
        BeanUtils.copyProperties(tbSellerResult, sellerVO);

        //赋值  返回
        seckillGoodsVO.setSellerVO(sellerVO);
        return seckillGoodsVO;
    }

    //根据id查询redis中的秒杀商品信息
    @Override
    public SeckillGoodsVO selectBySeckillId(Long sekillGId) {
        SeckillGoodsVO vo = (SeckillGoodsVO) redisTemplate.boundHashOps("SeckillGoodsVO").get(sekillGId);
        return vo;
    }


    @Override
    public Result SeckillSubOrder(String userName, Long sekillGId) {
        //1.获取redis中秒杀数据
        SeckillGoodsVO vo = (SeckillGoodsVO) redisTemplate.boundHashOps("SeckillGoodsVO").get(sekillGId);

        //2.判断redis中的秒杀数据是否为空
        if (vo == null) {
            return Result.ZHRESPONSE(ResultEnum.NOT_SECKILLGOODS);//没有秒杀商品
        }
        //3.校验时间   结束时间 - 当前时间   小于等于0=秒杀时间结束
        long now = new Date().getTime();
        long end = vo.getEndTime().getTime();
        if ((end - now) <= 0) {
            return Result.ZHRESPONSE(ResultEnum.SECKILL_TIME_END);//秒杀时间结束
        }
        //4.校验库存是否充足
        if (vo.getStockCount() <= 0) {
            return Result.ZHRESPONSE(ResultEnum.STOCKCOUNT_NOT_NULL);//库存为空
        }

        //5.扣减redis库存
        vo.setStockCount(vo.getStockCount() - 1);
//        为什么要在redis中一直扣减库存到0才去数据库减
        //6.更新redis
        redisTemplate.boundHashOps("SeckillGoodsVO").put(vo.getId(), vo);

        //7.如果库存为0 更新数据库
        if (vo.getStockCount() == 0) {
            TbSeckillGoods seckillGoods = new TbSeckillGoods();
            BeanUtils.copyProperties(vo, seckillGoods);
            seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
        }

        //8.生成订单
        SeckillOrderVO orderVO = new SeckillOrderVO();
        IdWorker idWorker = new IdWorker();
        orderVO.setId(idWorker.nextId());
        orderVO.setSeckillId(vo.getId());
        orderVO.setMoney(vo.getCostPrice());//商城价
        orderVO.setUserId(userName);
        orderVO.setSellerId(vo.getSellerId());
        orderVO.setCreateTime(new Date());
        orderVO.setStatus("0");

        TbSeckillOrder order = new TbSeckillOrder();
        BeanUtils.copyProperties(orderVO, order);
        orderService.generateSeckillOrder(order);

        return Result.ZHRESPONSE(ResultEnum.SECKILL_ORDER_SUBMIT_SUCCESS);// TODO: 2023/6/7 秒杀提交订单
    }
}
